#ifndef _DISK_INFO_H_
#define _DISK_INFO_H_

#include <stdint.h>
#include <sys/statfs.h>
// #include <sys/vfs.h>
#include <mntent.h>
#include <stdio.h>

#ifdef __x86_64__
#define DISK_STAT_ITEM_SIZE uint64_t
#elif defined(__i386__)
#define DISK_STAT_ITEM_SIZE uint32_t
#elif defined(__aarch64__)
#define DISK_STAT_ITEM_SIZE uint64_t
#elif defined(_WIN64)
#define DISK_STAT_ITEM_SIZE uint64_t
#elif defined(__arm__) && !defined(__aarch64__)
#define DISK_STAT_ITEM_SIZE uint32_t
#else
#define DISK_STAT_ITEM_SIZE uint32_t
#endif

// disk
int GetMountedOnListNumber();
int GetMountedOnList(int num, char *mounted);
/**
 * @brief Get the Disk Info object
 * 
 * @param mounted 挂载点
 * @param sfs   f_bsize 块大小（一般是4096）
 *              f_blocks 总块数，f_blocks*f_bsize/1024即总空间大小（KB）
 *              f_bavail 剩余可使用块数， f_bavail*f_bsize/1024即剩余空间大小（KB）
 * @return int 
 */
int GetDiskInfo(char *mounted, struct statfs *sfs);

// io
// 对于主设备号及对应设备的含义，查看 cat /proc/devices 可以获取到
// 一般来说主设备号8代表SCSI/SATA/USB 磁盘（如现代硬盘和 SSD），259代表 NVMe协议的高速 SSD，179 嵌入式设备的 SD 卡或 eMMC 存储（如树莓派的 SD 卡）。
// ​​次设备号规则(仅存储设备)
// 次设备号 0：整块磁盘（如 /dev/sda）。
// 次设备号 1：第一个分区（如 /dev/sda1）。
// 次设备号 2：第二个分区（如 /dev/sda2）。
struct DiskStatus
{
    char device_name[256];                      // 设备名称
    DISK_STAT_ITEM_SIZE major_num;              // 主设备号
    DISK_STAT_ITEM_SIZE minor_num;              // 次设备号
    DISK_STAT_ITEM_SIZE read_complete;          // 成功完成读的总次数
    DISK_STAT_ITEM_SIZE read_merge;             // 合并读次数
    DISK_STAT_ITEM_SIZE read_sectors;           // 读扇区的次数（通常，一个扇区是 512 字节）
    DISK_STAT_ITEM_SIZE read_time_ms;           // 读操作花费的时间（ms），这是所有读操作所花费的毫秒数
    DISK_STAT_ITEM_SIZE write_complete;         
    DISK_STAT_ITEM_SIZE write_merge;
    DISK_STAT_ITEM_SIZE write_sectors;
    DISK_STAT_ITEM_SIZE write_time_ms;
    DISK_STAT_ITEM_SIZE io_current_in_process;  // 正在处理的输入/输出请求数，当前进行中的 I/O 请求数
    DISK_STAT_ITEM_SIZE io_time_ms;             // I/O操作上花费的毫秒数，自系统启动以来，所有 I/O 操作的总耗时（包括读、写、队列等待时间）
    DISK_STAT_ITEM_SIZE io_weighted_time_ms;    // 输入/输出操作花费的加权毫秒数
};

struct IoStatusInfo {
    FILE *fp;
    int disk_num;
    struct DiskStatus *nstatus;
    float *io_usage_rate;  // present(%) unit
    DISK_STAT_ITEM_SIZE *write_speed;   // bytes per time
    DISK_STAT_ITEM_SIZE *read_speed;    // bytes per time
};
int IOUsageRateInit(struct IoStatusInfo *info);
void IOUsageRateDeinit(struct IoStatusInfo *info);
int GetIOUsageRate(struct IoStatusInfo *info, int cross_time_ms);  // cross_time: the time(ms) between call this function

#endif /* _DISK_INFO_H_ */
